import traceback

from flask import Blueprint, g
from flask_restful import Resource, Api, reqparse, marshal

from common.models.account import User, Channel, UserChannel, News
from common import db, cache
from common.model_fields.model_fields import user_fields, user_channel_fields, news_fields
from common.utils.jwt_utils import create_login_token, refresh_token
from common.utils.login_util import login_required

account_bp = Blueprint('account_bp', __name__)
api = Api(account_bp)


class RegisterUser(Resource):
    """
    用户注册
    """

    def post(self):
        # 获取参数
        parser = reqparse.RequestParser()
        parser.add_argument('account')
        parser.add_argument('password')
        args = parser.parse_args()
        account = args.get('account')
        password = args.get('password')
        # 验证参数的完整
        if not all([account, password]):
            return {'message': 'fail', 'code': 407, 'error': '注册信息不能为空'}
        # 验证账号是否存在
        user = User.query.filter_by(account=account).first()
        if user:
            return {'message': 'fail', 'code': 407, 'error': '账号已存在'}
        # 创建用户
        user = User(account=account, password=password)
        db.session.add(user)
        db.session.commit()
        return {'message': 'ok', 'code': 200, 'data': marshal(user, user_fields)}


class LoginUser(Resource):
    """
    用户登录
    """

    def post(self):
        parser = reqparse.RequestParser()
        parser.add_argument('account')
        parser.add_argument('password')
        args = parser.parse_args()
        account = args.get('account')
        password = args.get('password')
        # 判断用户是否存在
        user = User.query.filter_by(account=account, password=password).first()
        if not user:
            return {'message': 'fail', 'code': 407, 'error': '账号密码错误'}

        token, refresh_token = create_login_token(user.uid)
        return {'message': 'ok', 'code': 200, 'data': {'token': token, 'refresh_token': refresh_token}}


class UpdateUserInfo(Resource):
    """
    修改用户信息
    """

    @login_required
    def post(self):
        parser = reqparse.RequestParser()
        parser.add_argument('user_name')
        args = parser.parse_args()
        user_name = args.get('user_name')
        try:
            user = User.query.get(g.user_id)
            user.user_name = user_name
            db.session.commit()
        except:
            error = traceback.format_exc()
            print('UpdateUserInfo error:{}'.format(error))
            return {'message': 'fail', 'code': 501}
        return {'message': 'ok', 'code': 200, 'data': marshal(user, user_fields)}


class GetUser(Resource):
    """
    获取当前登录的用户信息
    """

    @login_required
    def get(self):
        user_id = g.user_id
        # 从缓存中读取
        user = cache.get('user_id_{}'.format(user_id))
        # 如果找到数据
        if user:
            return {'message': 'ok', 'code': 200, 'data': marshal(user, user_fields)}

        user = User.query.get(user_id)
        cache.set('user_id_{}'.format(user_id), user, timeout=30)
        return {'message': 'ok', 'code': 200, 'data': marshal(user, user_fields)}


class TokenPut(Resource):
    """
    无感刷新token
    """

    def post(self):
        token = refresh_token()
        if token:
            return {'message': 'ok', 'code': 200, 'data': {'token': token}}
        else:
            return {'message': 'fail token', 'code': 407}


class AddUserChannel(Resource):
    """
    普通用户收藏频道
    """

    @login_required
    def post(self):
        user_id = g.user_id
        parser = reqparse.RequestParser()
        parser.add_argument('channel_id')
        args = parser.parse_args()
        channel_id = args.get('channel_id')
        if not channel_id:
            return {'code': 400, 'message': 'channel_id is null', 'data': '你不中'}
        channel = Channel.query.get(channel_id)
        if not channel:
            return {'message': 'channel_id not have', 'code': 400, 'data': 'no have'}
        user_channel = UserChannel.query.filter_by(cid=channel_id, uid=user_id).count()
        if user_channel >= 1:
            return {"message": 'fail', 'code': 500, 'data': '不好意思, 你添加过了'}
        try:
            user_channel = UserChannel(uid=user_id, cid=channel_id)
            db.session.add(user_channel)
            db.session.commit()
            return {'message': 'success', 'code': 201, 'data': marshal(user_channel, user_channel_fields)}
        except:
            error = traceback.format_exc()
            return {'message': error, 'code': 401, 'data': 'add fail'}


class AddNews(Resource):
    """
    新增资讯
    """

    @login_required
    def post(self):
        user_id = g.user_id
        parser = reqparse.RequestParser()
        parser.add_argument('title')
        parser.add_argument('content')
        parser.add_argument('cid', type=int)
        args = parser.parse_args()
        title = args.get('title')
        content = args.get('content')
        cid = args.get('cid')
        if len(title) > 64:
            return {'code': 500, 'message': '标题过长'}
        channel = Channel.query.get(cid)
        if channel:
            news = News(user_id=user_id, title=title, content=content, channel_id=cid)
            db.session.add(news)
            db.session.commit()
            return {'code': 200, 'message': 'ok'}
        return {'code': 500, 'message': 'add fail'}


class GetNewsList(Resource):
    """
    获取资讯列表

    获取用户下频道的资讯（用户关注的频道的资讯----不涉及是否是用户发布的）

    获取用户发布的资讯
    """

    @login_required
    def get(self):
        user_id = g.user_id
        data = {}
        try:
            news_list = News.query.filter_by(user_id=user_id).order_by(News.nid.desc()).all()
            for news in news_list:
                name = news.channel.cname
                if name not in data:
                    data.update({name: [marshal(news, news_fields)]})
                else:
                    data[name].append(marshal(news, news_fields))
            return {'message': 'ok', 'code': 200, 'data': data}
        except:
            error = traceback.format_exc()
            print('GetNewsList error {}'.format(error))
            return {'message': 'fail', 'code': 500}


# {'cctv1': [{news1}, {new2}],
#  'cctv2': [{news1}, {new2}],
#  }


class GetUserChannelNewsList(Resource):
    """
    获取用户关注的频道中的资讯（当前频道下的所有资讯）
    """

    @login_required
    def get(self):
        user_id = g.user_id
        user = User.query.get(user_id)
        # 获取用户下关注的频道
        user_channel = user.channels
        print('user_channel:{}'.format(user_channel))
        data = {}
        try:
            for channel in user_channel:
                # if not channel.news:
                #     continue
                # 获取频道下的所有资讯
                news_list = channel.news
                data.update({channel.cname: marshal(news_list, news_fields)})
            return {'message': 'ok', 'code': 200, 'data': data}
        except:
            error = traceback.format_exc()
            return {"message": "fail", "code": 401, "error": error}


class UpdateUserNews(Resource):
    @login_required
    def put(self):
        """
        修改用户资讯
        """
        # 获取参数
        user_id = g.user_id
        parser = reqparse.RequestParser()
        parser.add_argument('content')
        parser.add_argument('title')
        parser.add_argument('nid')
        args = parser.parse_args()
        nid = args.get('nid')
        title = args.get('title')
        content = args.get('content')

        # 获取资讯对象数据
        new = News.query.get(nid)
        try:
            if new:
                # 判断是不是这个用户的资讯
                if new.user_id == user_id:
                    # 如果资讯内容存在，更新内容
                    if content:
                        new.content = content
                    # 如果标题存在并且长度符合要求，更新标题
                    if title and len(title) <= 64:
                        new.title = title
                    db.session.commit()
                    return {'code': 200, 'message': 'ok'}
                else:
                    return {'code': 403, 'message': 'Not permission'}
            return {'code': 407, 'message': 'Params is error'}
        except:
            error = traceback.format_exc()
            print('error {}'.format(error))
            return {'code': 500, 'message': 'Server is error'}


class DeleteUserChannel(Resource):
    """
    删除用户关注的频道列表

    思路一：
        1、先强制登录，获取用户id
        2、获取要删除的频道id(从前端获取)
        3、判断从前端获取的这个频道id是否存在
        4、删除数据（user.channels.remove(channel)    channel.delete()）
    """

    @login_required
    def delete(self):
        user_id = g.user_id
        user = User.query.get(user_id)

        parser = reqparse.RequestParser()
        parser.add_argument('channel_id')
        args = parser.parse_args()
        channel_id = args.get('channel_id')
        UserChannel.query.filter_by(uid=user_id, cid=channel_id).delete()
        db.session.commit()
        return {'message': 'ok', 'code': 200}
        # channel = Channel.query.get(channel_id)
        # if channel:
        #     if channel in user.channels:
        #         user.channels.remove(channel)
        #         db.session.commit()
        #         return {"message": "ok", "code": 200}
        #     return {'message': 'Channel id is error', 'code': 500}
        # else:
        #     return {'message': 'Channel is not exist', 'code': 500}


api.add_resource(RegisterUser, '/register_user', endpoint='register_user')
api.add_resource(LoginUser, '/login_user', endpoint='login_user')
api.add_resource(UpdateUserInfo, '/update_user_info', endpoint='update_user_info')
api.add_resource(GetUser, '/get_user', endpoint='get_user')
api.add_resource(TokenPut, '/put_token', endpoint='put_token')
api.add_resource(AddUserChannel, '/add_user_channel', endpoint='add_user_channel')
api.add_resource(UpdateUserNews, '/update_user_news', endpoint='update_user_news')
api.add_resource(AddNews, '/add_news', endpoint='add_news')
api.add_resource(GetNewsList, '/get_news_list', endpoint='get_news_list')
api.add_resource(GetUserChannelNewsList, '/get_user_channel_news_list', endpoint='get_user_channel_news_list')
api.add_resource(DeleteUserChannel, '/delete_user_channel', endpoint='delete_user_channel')
